﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DuplicateCheck.Data;
using DuplicateCheck.Entity;
using System.Data.SqlClient;
using System.Configuration;
namespace Logica.BD_Administrator
{
    public class BDManager
    {
        public SqlDataReader queueCheck(DuplicateCheck.Entity.Model.DuplicateRules businessRules)
        {
            //string query = "select ID,CLASS,WORK_STATUS,ERROR_CODE from dbo.QUEUES where QUEUE = '" + Configuration.inputQueue + "' and WORK_STATUS IN (2,4,7) and TYPE = 2 and CLASS in (" + businessRules.getAllClasses() + ") ORDER BY CLASS";            

            string query = "SELECT TOP "+ Convert.ToInt32(ConfigurationManager.AppSettings["topQuery"].ToString())+" Q.ID, Q.WORK_STATUS,Q.QUEUE,Q.CLASS, A.* from QUEUES Q,ATTRIBUTES A " +
            "where A.OBJECT_ID = Q.ID " +
            "and Q.QUEUE = '"+ConfigurationManager.AppSettings["inputQueue"].ToString()+"' " +
            "and Q.CLASS IN (" + businessRules.getAllClasses() + ") "+
            "and Q.WORK_STATUS IN (2,4,7) and Q.TYPE = 2 "+
            "ORDER BY Q.CLASS, Q.ID";


           // Services.sendLog(629,"Ejecutando query: "+query+" a la base de datos de INFOIMAGE.",Services.errorType.Information_Message);
            SqlDataClass dataClass = new SqlDataClass();
            return dataClass.SQLRead(query);
        }

        public bool processDocument(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DuplicateService businessRules)
        {
            string ID = Document.getIDValue();
            Services.sendLog(607, "Procesando Documento con Object ID: [" + ID + "]", Services.errorType.Information_Message);
            
            //1. procesar inconsistencias
            //2. procesar excepciones
            //3. procesar duplicados
            #region Rejected

            foreach (Entidades.Model.Rejected rejected in businessRules.rejectedClass)
            {                
                if(Document.getValue("CLASS").Equals(rejected.Name))//si es la misma clase
                    if(Document.getValue(rejected.FieldName).Equals(rejected.FieldValue))//documento rechazado
                        return rejectDocument(Document, rejected);
            }
            Services.sendLog(607, "El documento no fue rechazado", Services.errorType.Information_Message);    
            //el documento no fue rechazado 
            #endregion

            #region Inconsistencies

            Entidades.Model.Incosistence incosistence = verifyInconsistencies(Document, businessRules);
            if (incosistence != null)
                return verifyAction(Document, incosistence);
            else
                Services.sendLog(631, "El documento [" + ID + "] no es inconsistente", Services.errorType.Information_Message);                    
            #endregion

            #region Exceptions
            Entidades.Model.DocClassExc exception = verifyException(Document, businessRules);
            if (exception != null)
                return verifyAction(Document, exception);
            else
                Services.sendLog(634, "El documento [" + ID + "] no es una excepcion", Services.errorType.Information_Message);
            #endregion

            #region Duplicates
            Entidades.Model.DocClass document = verifyDuplicateClass(Document, businessRules);
            if (document != null)
                return verifyAction(Document, document);
            else
            {
                Services.sendLog(635, "La clase documental " + ID + " no esta configurada en las reglas del negocio", Services.errorType.Error_Message);
                return false;
            }
            #endregion    
           

           
        }

        #region verify CLASS in Business Rules

        private Entidades.Model.Incosistence verifyInconsistencies(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DuplicateService businessRules)
        {
            if (Document != null)
            {
                Entidades.Model.Incosistence incosistence = businessRules.getIncosistence(Document.getValue("CLASS"));
                if (incosistence == null)                                  
                    return null;
                

                foreach (Entidades.Model.IndexField field in incosistence.Fields)
                {                    
                    if (String.IsNullOrEmpty(Document.getValue(field.Name)))//el campo requerido no puede ser null ni en blanco                                               
                        return incosistence;//se retorna la inconsistencia para q sea procesada (campo requerido en blanco)                                                
                }
                
                return null;
            }
            else
                return null;
        }

        private Entidades.Model.DocClassExc verifyException(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DuplicateService businessRules)
        {
            if (Document != null)                         
                return businessRules.getException(Document.getValue("CLASS"),Document.getValue("OBJECT_NAME"));                                   
            else
                return null;
        }

        private Entidades.Model.DocClass verifyDuplicateClass(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DuplicateService businessRules)
        {
            if (Document != null)
                return businessRules.getDuplicateClass(Document.getValue("CLASS"),Document.getValue("UNI_DOCUMENTAL"));  //en lab Unisys
               //return businessRules.getDuplicateClass(Document.getValue("CLASS"),Document.getValue("UNI_DOC"));  //en ambiente BCR
            else
                return null;
        }

        #endregion

        #region Actions
        /*
         *acciones:
         *1: Versionar
         *2: Reclasificar
         *3: Mover a otra cola (si no se especifica se mueve a la cola default)
         */
        
        //auxiliar method
        private string[] sortArray(string[] array)
        {
            array = array.Distinct().ToArray();
            Array.Sort(array);
            return array;
        }

        #region verifyAction
        private bool verifyAction(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.Incosistence incosistence)
        {
            Services.sendLog(632, "Procesando documento [" + Document.getIDValue() + "] inconsistente", Services.errorType.Information_Message);

            string[] actions = incosistence.DocActions.Split(',');//docActions es un campo con los id de las acciones separadas por comas
            actions = sortArray(actions);//elmina repetidos y ordena el arreglo

            Logica.InfoImage_Folder.IIF_Manager infoImage = null;

            bool processState = true;//bandera q indica el estado del proceso
            bool sendToDefault = true;//bandera que indica enviar el documento a la cola default

            #region Processing Actions

            foreach (string action in actions)
            {
                int numberAction = 0;

                #region Change Action to NumberCode

                try
                {
                    numberAction = Convert.ToInt32(action);
                }
                catch (Exception e)
                {
                    Services.sendLog(65, "El parametro DocActions de la inconsistencia [" + incosistence.Name + "] tiene valores invalidos. Valor encontrado: " + action, Services.errorType.Error_Message);
                    continue;
                }

                #endregion

                switch (numberAction)
                {
                    case 1:
                        {
                            bool tempState = version(Document, null);//version 1 historico 0
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de versionar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 2:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.Reclasify(Document.getIDValue(), incosistence.NewName);//reclasificar
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de reclasificar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 3:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), incosistence.outputQueue);//enviar a cola especifica
                            sendToDefault = false;//no enviar el documento a la cola default
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de enviar a la cola, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    default:
                        {
                            Services.sendLog(65, "El parametro DocActions de la inconsistencia [" + incosistence.Name + "] tiene valores invalidos. Valor encontrado: " + numberAction, Services.errorType.Error_Message);
                            continue;
                        }
                }

            }

            #endregion


            if (sendToDefault)
            {
                try
                {
                    if (infoImage == null)//conexion cerrada
                        infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                }
                catch (Exception e)
                {
                    Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                    return false;
                }

                bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), Configuration.outputQueue);//envio a la cola default parametrizada en el sistema
                if (processState)//si el estado del proceso sigue siendo true
                    processState = tempState;//el estado sera el estado del proceso de enviar a la cola default, de lo contrario ya dio un error antes y se mantendra el reporte del error
            }

            if (infoImage != null)//si se abrio una conexion con InfoImage
                infoImage.DestroyIIFClientExplicit();

            return processState;
           

        }

        private bool verifyAction(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DocClassExc exception)//procesando Excepcion
        {
            Services.sendLog(633, "Procesando Excepcion [" + Document.getIDValue() + "]", Services.errorType.Information_Message);            

            string[] actions = exception.DocActions.Split(',');//docActions es un campo con los id de las acciones separadas por comas
            actions = sortArray(actions);//elmina repetidos y ordena el arreglo

            Logica.InfoImage_Folder.IIF_Manager infoImage = null;

            bool processState = true;//bandera q indica el estado del proceso
            bool sendToDefault = true;//bandera que indica enviar el documento a la cola default
            #region Processing Actions

            foreach (string action in actions)
            {
                int numberAction = 0;

                #region Change Action to NumberCode

                try
                {
                    numberAction = Convert.ToInt32(action);
                }
                catch (Exception e)
                {
                    Services.sendLog(65, "El parametro DocActions de la excepcion [" + exception.ClassName + "] tiene valores invalidos. Valor encontrado: " + action, Services.errorType.Error_Message);
                    continue;
                }

                #endregion

                switch (numberAction)
                {
                    case 1:
                        {
                            bool tempState = version(Document, null);//version 1 historico 0
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de versionar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 2:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.Reclasify(Document.getIDValue(), exception.NewName);//reclasificar
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de reclasificar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 3:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), exception.outputQueue);//enviar a cola especifica
                            sendToDefault = false;//no enviar el documento a la cola default
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de enviar a la cola, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    default:
                        {
                            Services.sendLog(65, "El parametro DocActions de la excepcion [" + exception.ClassName + "] tiene valores invalidos. Valor encontrado: " + action, Services.errorType.Error_Message);
                            continue;
                        }
                }

            }

            #endregion


            if (sendToDefault)
            {
                try
                {
                    if (infoImage == null)//conexion cerrada
                        infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                }
                catch (Exception e)
                {
                    Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                    return false;
                }

                bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), Configuration.outputQueue);//envio a la cola default parametrizada en el sistema
                if (processState)//si el estado del proceso sigue siendo true
                    processState = tempState;//el estado sera el estado del proceso de enviar a la cola default, de lo contrario ya dio un error antes y se mantendra el reporte del error
            }

            if (infoImage != null)//si se abrio una conexion con InfoImage
                infoImage.DestroyIIFClientExplicit();

            return processState;
        }

        private bool verifyAction(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.DocClass docClass)
        {
            Services.sendLog(607, "Procesando documento [" + Document.getIDValue() + "], verificando duplicados", Services.errorType.Information_Message);
            string[] actions = docClass.DocActions.Split(',');//docActions es un campo con los id de las acciones separadas por comas
            actions = sortArray(actions);//elmina repetidos y ordena el arreglo

            Logica.InfoImage_Folder.IIF_Manager infoImage = null;

            bool processState = true;//bandera q indica el estado del proceso
            bool sendToDefault = true;//bandera que indica enviar el documento a la cola default
            #region Processing Actions

            foreach (string action in actions)
            {
                int numberAction = 0;

                #region Change Action to NumberCode

                try
                {
                    numberAction = Convert.ToInt32(action);
                }
                catch (Exception e)
                {
                    Services.sendLog(65, "El parametro DocActions del documento [" + docClass.Name + "] tiene valores invalidos. Valor encontrado: " + action, Services.errorType.Error_Message);
                    continue;
                }

                #endregion

                switch (numberAction)
                {
                    case 1:
                        {
                            bool tempState = version(Document,docClass);//encontrar duplicados y versionar
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de versionar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 2:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.Reclasify(Document.getIDValue(), docClass.NewName);//reclasificar
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de reclasificar, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    case 3:
                        {
                            try
                            {
                                if (infoImage == null)//conexion cerrada
                                    infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                            }
                            catch (Exception e)
                            {
                                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                                return false;
                            }
                            bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), docClass.outputQueue);//enviar a cola especifica
                            sendToDefault = false;//no enviar el documento a la cola default
                            if (processState)//si el estado del proceso sigue siendo true
                                processState = tempState;//el estado sera el estado del proceso de enviar a la cola, de lo contrario ya dio un error antes y se mantendra el reporte del error
                        } break;
                    default:
                        {
                            Services.sendLog(65, "El parametro DocActions del documento [" + docClass.Name + "] tiene valores invalidos. Valor encontrado: " + action, Services.errorType.Error_Message);
                            continue;
                        }
                }

            }

            #endregion


            if (sendToDefault)
            {
                try
                {
                    if (infoImage == null)//conexion cerrada
                        infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
                }
                catch (Exception e)
                {
                    Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                    return false;
                }

                bool tempState = infoImage.SendToWorkflow(Document.getIDValue(), Configuration.outputQueue);//envio a la cola default parametrizada en el sistema
                if (processState)//si el estado del proceso sigue siendo true
                    processState = tempState;//el estado sera el estado del proceso de enviar a la cola default, de lo contrario ya dio un error antes y se mantendra el reporte del error
            }

            if (infoImage != null)//si se abrio una conexion con InfoImage
                infoImage.DestroyIIFClientExplicit();

            return processState;
        }
        #endregion

        #region Actions Slave

        private bool rejectDocument(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/, Entidades.Model.Rejected rejectedClass)
        {
            Services.sendLog(638, "Procesando documento [" + Document.getIDValue() + "] rechazado", Services.errorType.Information_Message);
            
            Logica.InfoImage_Folder.IIF_Manager infoImage = null;
            try
            {                        
                infoImage = new Logica.InfoImage_Folder.IIF_Manager();//referencia a IIF
            }
            catch (Exception e)
            {
                Services.sendLog(204, e.Message, Services.errorType.Error_Message);
                return false;
            }

            bool processState = true;
            bool tempState;

            tempState=infoImage.Reclasify(Document.getIDValue(),rejectedClass.NewName);//se reclasifica el documento rechazado
            if (processState)//si el estado del proceso sigue siendo true
                processState = tempState;//el estado sera el estado del proceso de reclasificar, de lo contrario ya dio un error antes y se mantendra el reporte del error


            tempState = infoImage.SendToWorkflow(Document.getIDValue(), rejectedClass.outputQueue);
            if (processState)//si el estado del proceso sigue siendo true
                processState = tempState;//el estado sera el estado del proceso de enviar a la cola, de lo contrario ya dio un error antes y se mantendra el reporte del error

            if (infoImage != null)//si se abrio una conexion con InfoImage
                infoImage.DestroyIIFClientExplicit();

            return processState;
              
            //Services.sendLog(66, "La clase documental " + reader.GetString(reader.GetOrdinal("CLASS")) + " no esta configurada en las reglas del negocio",Services.errorType.Error_Message);
            //return false;
        }
        
        private string getAllDuplicateFields(Entidades.Model.duplicateDocument Document/*SqlDataReader reader*/,Entidades.Model.DocClass doc)
        {
            string result = "";
            foreach (Entidades.Model.IndexField field in doc.Fields)
            {
                result += "AND " + field.Name + " = '" + Document.getValue(field.Name) + "' ";
            }            
            return result;            
        }

        public List<Entidades.Model.duplicateDocument> convertReaderToList(SqlDataReader reader)
        {
            List<Entidades.Model.duplicateDocument> documentsList = new List<Entidades.Model.duplicateDocument>();
           // int i = 0;
            while (reader.Read())
            {

                //Services.sendLog(665, "Creando Documento: " + i.ToString(), Services.errorType.Information_Message); i++;
                Entidades.Model.duplicateDocument document = new Entidades.Model.duplicateDocument();
                document.Fields = new List<Entidades.Model.IndexField>();
                try
                {
                    int cont = 0;

                    while (true)
                    {
                        Entidades.Model.IndexField field = new Entidades.Model.IndexField();
                        field.Name = reader.GetName(cont);//en caso de llegar a la ulima columna envia excepcion de index out of...                        
                        field.Value = reader.GetSqlValue(cont).ToString();                        
                        //Services.sendLog(665, "Creando Campo: " + cont.ToString()+" Nombre: "+field.Name+" Valor: "+field.Value , Services.errorType.Information_Message);
                        cont++;
                        document.Fields.Add(field);
                    }
                }
                catch (Exception e) { /*Services.sendLog(665, "Error al crear campo "+e.Message, Services.errorType.Information_Message); */}
                finally
                {
                    documentsList.Add(document);//agregar el documento a la lista
                }
            }
            return documentsList;
        }

        private bool existDateNull(List<Entidades.Model.duplicateDocument> duplicates)//retorna true si existe null en el campo VENCE
        {
            foreach (Entidades.Model.duplicateDocument document in duplicates)
            {                
                string vence=document.getVENCEValue();
                if (String.IsNullOrEmpty(vence)||(vence.ToUpper().Equals("NULL")))//encuentra un documento con vence en blanco o null
                    return true;
            }
            return false;
        }

        private List<Entidades.Model.duplicateDocument> sort(int tamano, List<Entidades.Model.duplicateDocument> izquierda, List<Entidades.Model.duplicateDocument> derecha)
        {
            int i = 0, j = 0;
            DateTime date1,date2;
            List<Entidades.Model.duplicateDocument> sortedList = new List<Entidades.Model.duplicateDocument>();
            for (int k = 0; k < tamano; k++)
            {


                if (i >= izquierda.Count)
                { sortedList.Add(derecha[j]); j++; continue; }
                else
                { date1 = Convert.ToDateTime(izquierda[i].getVENCEValue()); }

                if (j >= derecha.Count)
                { sortedList.Add(izquierda[i]); i++; continue; }
                else
                { date2 = Convert.ToDateTime(derecha[j].getVENCEValue()); }
                
                if(DateTime.Compare(date1,date2)<0)//agrega a la lista la fecha menor
                { sortedList.Add(izquierda[i]); i++; }
                else
                { sortedList.Add(derecha[j]); j++; }

            }
            return sortedList;
        }



        private List<Entidades.Model.duplicateDocument> reOrganizeData(List<Entidades.Model.duplicateDocument> duplicates)
        {

            if (duplicates.Count <= 1)
                return duplicates;
            else
            {
                int mitad = (duplicates.Count) / 2;
                List<Entidades.Model.duplicateDocument> der;


                if (((duplicates.Count) % 2) == 0)
                    der = duplicates.GetRange(mitad, mitad);
                else
                    der = duplicates.GetRange(mitad, mitad + 1);

                List<Entidades.Model.duplicateDocument> izq = duplicates.GetRange(0, mitad);


                return sort(duplicates.Count, reOrganizeData(izq), reOrganizeData(der));
            }
        }

        public List<Entidades.Model.duplicateDocument> deleteDocuments(List<Entidades.Model.duplicateDocument> documentsDuplicates, string principalDocumentID)
        {
            bool wasVersioned = false;
            int i=0;
            while(i<documentsDuplicates.Count)            
            {
                Entidades.Model.duplicateDocument duplicateDocument = documentsDuplicates[i];
                
                foreach (string queue in Configuration.searchQueues)//buscar que se encuentre el documento dentro de las colas configuradas
                {
                    //el documento debe estar en la cola configurada o es el documento que se esta procesando                    
                    if ((duplicateDocument.getValue("UBICACION").Equals(queue)) || (duplicateDocument.getIDValue().Equals(principalDocumentID)))
                    {
                        wasVersioned = true;
                        break;                      
                    }
                }

                if (!(wasVersioned))
                {
                    Services.sendLog(0, "Documento[" + duplicateDocument.getIDValue() + "] duplicado descartado y no versionado. La cola " + duplicateDocument.getValue("UBICACION") + " no ha sido configurada", Services.errorType.Information_Message);
                    documentsDuplicates.RemoveAt(i);
                }
                else
                {
                    i++; wasVersioned = false;
                }
            }
            return documentsDuplicates;
            
        }

        private bool version(Entidades.Model.duplicateDocument Document/*SqlDataReader queue*/, Entidades.Model.DocClass docClass)
        {
            if (docClass == null)//version 1 historico 0
            {
                SqlDataClass queryToDataBase = new SqlDataClass();
                int result;
                try
                {
                    Services.sendLog(622,"Ejecutando el Store Procedure: " + Configuration.updateCommand + " a la base de datos de INFOIMAGE (Versionando sin duplicados).",Services.errorType.Information_Message);
                    result = queryToDataBase.SQLUpdate(Document.getIDValue(), "1", "0",true);//versionamiento sin buscar duplicados
                }
                catch (Exception e)
                {
                    Services.sendLog(155, "Error al ejecutar el store procedue: " + Configuration.updateCommand + " Error[" + e.Message + "]", Services.errorType.Error_Message);
                    return false;
                }

                if (result < 1)
                {
                    Services.sendLog(155, "Error al ejecutar el store procedue: " + Configuration.updateCommand, Services.errorType.Error_Message);
                    return false;
                }
                else
                {
                    Services.sendLog(286, "Store Procedure: " + Configuration.updateCommand + " ejecutado con exito.", Services.errorType.Information_Message);
                    return true;
                }
            }
            else//versionar buscando duplicados
            {
                Services.sendLog(639, "Buscando Duplicados de: " + Document.getIDValue(), Services.errorType.Information_Message);
                string duplicatesQuery = 
                    "Select A.OBJECT_ID, A."+docClass.DateFieldName+" AS VENCE,"+ 
                   "CONVERT(DATE,DATEADD(day, CAST(substring(A.OBJECT_ID,3,3) AS int)-1,CONVERT(datetime,'20'+substring(A.OBJECT_ID,1,2)+'0101',112))) AS FECHA_REGISTRO,"+
                   "CASE WHEN Q.QUEUE IS NULL THEN 'ARCHIVE' ELSE Q.QUEUE END AS UBICACION "+
                   "From ATTRIBUTES A "+
                           "LEFT OUTER JOIN QUEUES Q ON Q.ID = A.OBJECT_ID "+
                    "Where A.OBJECT_CLASS = '"+docClass.Name+"'"+
                       getAllDuplicateFields(Document,docClass) +
                    "AND A.UNI_DOCUMENTAL= '"+docClass.unitName+"'"+//lab Unisys
                    //"AND A.UNI_DOC= '"+docClass.unitName+"'"+//ambiente BCR
                    "Order by FECHA_REGISTRO DESC, A.OBJECT_ID DESC";

                SqlDataClass queryToDataBase = new SqlDataClass();
                Services.sendLog(629, "Ejecutando query: " + duplicatesQuery + " a la base de datos de INFOIMAGE.", Services.errorType.Information_Message);

                SqlDataClass dataClass = new SqlDataClass();
                SqlDataReader duplicates=null;

                try
                {
                    duplicates =  dataClass.SQLRead(duplicatesQuery);
                    if (duplicates == null)
                    {
                        Services.sendLog(640, "No se encontraron documentos duplicados del documento[" + Document.getIDValue() + "]", Services.errorType.Information_Message);
                        return version(Document, null);//versionar sin buscar duplicados
                    }
                }
                catch (Exception sqlExc)
                {
                    Services.sendLog(155, "Imposible ejecutar query a la Base de Datos de InfoImage: " + sqlExc.Message, Services.errorType.Error_Message);
                    return false;
                }

                if (duplicates.HasRows)
                {
                    
                    List<Entidades.Model.duplicateDocument> documentsDuplicates = convertReaderToList(duplicates);
                    duplicates.Close();
                    Services.sendLog(665, "Se encontraron " + documentsDuplicates.Count.ToString() + " documentos duplicados", Services.errorType.Information_Message);

                    if (!(existDateNull(documentsDuplicates)))
                        documentsDuplicates=reOrganizeData(documentsDuplicates);

                    documentsDuplicates = deleteDocuments(documentsDuplicates, Document.getIDValue());//elmina documentos de colas no configuradas


                    #region Open Connection
                    try
                    {
                        dataClass.OpenConnection();
                    }
                    catch (Exception e)
                    {
                        Services.sendLog(151,"Imposible conectar con la base de datos de infoimage para hacer las actualizaciones de version",Services.errorType.Error_Message);
                        duplicates.Close();
                        return false;
                    }
                    #endregion

                    int version = 1;
                    for(int i=0;i<documentsDuplicates.Count;i++)
                    //foreach (Entidades.Model.duplicateDocument duplicateDocument in documentsDuplicates)
                    {
                        Entidades.Model.duplicateDocument duplicateDocument=documentsDuplicates[i];
                        string objID = duplicateDocument.getIDValue();
                        if (String.IsNullOrEmpty(objID))
                        {
                            Services.sendLog(113, "El documento no tiene el campo requerido OBJECT_ID correctamente indexado", Services.errorType.Error_Message);
                            continue;
                        }

                        /*bool wasVersioned = false;
                        foreach(string queue in Configuration.searchQueues)//buscar que se encuentre el documento dentro de las colas configuradas
                        {
                            //el documento debe estar en la cola configurada o es el documento que se esta procesando
                            if ((duplicateDocument.getValue("UBICACION").Equals(queue))||(duplicateDocument.getIDValue().Equals(Document.getIDValue())))
                            {
                                wasVersioned = true;*/
                                if ((i + 1) == documentsDuplicates.Count)
                                {
                                    Services.sendLog(0, "Versionando Documento: "+objID+" Version: "+version.ToString()+" Historico 0", Services.errorType.Information_Message);
                                    dataClass.SQLUpdate(objID, version.ToString(), "0", false);//ultimo documento duplicado
                                }
                                else
                                {
                                    Services.sendLog(0, "Versionando Documento: "+objID+" Version: "+version.ToString()+" Historico 1", Services.errorType.Information_Message);
                                    dataClass.SQLUpdate(objID, version.ToString(), "1", false);//no es el ultimo documento duplicado
                                }
                               /* break;
                            }
                        }
                        if (wasVersioned)
                        {      */                      
                            version++;//aumentar la version
                       // }
                    }

                    #region Close Connection
                    try
                    {
                        dataClass.CloseConnection();
                    }
                    catch (Exception e)
                    {
                        Services.sendLog(152, "Imposible cerrar la conexion con la base de datos de infoimage para hacer las actualizaciones de version", Services.errorType.Error_Message);
                        duplicates.Close();
                        return false;
                    }
                    #endregion
                    
                    return true;
                }
                else
                {
                    Services.sendLog(640, "No se encontraron documentos duplicados del documento[" + Document.getIDValue() + "]", Services.errorType.Information_Message);
                    duplicates.Close();
                    return version(Document, null);//versionar sin buscar duplicados
                }

            }
        }
        #endregion

        #endregion
    }
}
